package main

import (
    "fmt"
    "log"
    "math/rand"
    "net/url"
    "strconv"
    "time"
    //"encoding/json"

    "github.com/influxdata/influxdb/client"
)

const (
    MyHost        = "localhost"
    MyPort        = 8086
    MyDB          = "square_holes"
    MyMeasurement = "shapes"
)

func main() {

    u, err := url.Parse(fmt.Sprintf("http://%s:%d", MyHost, MyPort))
    if err != nil {
        log.Fatal(err)
    }

    conf := client.Config{
        URL:      *u,
        Username: "",
        Password: "",
    }

    con, err := client.NewClient(conf)
    if err != nil {
        log.Fatal(err)
    }

    dur, ver, err := con.Ping()
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("Happy as a Hippo! %v, %s", dur, ver)

    createDB(con)

    writePoints(con)

    countRecords(con)

    last10Shapes(con)
}

func queryDB(con *client.Client, cmd string) (res []client.Result, err error) {

    q := client.Query{
        Command:  cmd,
        Database: MyDB,
    }

    if response, err := con.Query(q); err == nil {
        if response.Error() != nil {
            return res, response.Error()
        }
        res = response.Results
    }
    return
}

func createDB(con *client.Client) {

    _, err := queryDB(con, fmt.Sprintf("create database %s", MyDB))
    if err != nil {
        log.Fatal(err)
    }
}

func writePoints(con *client.Client) {

    var (
        shapes     = []string{"circle", "rectangle", "square", "triangle"}
        colors     = []string{"red", "blue", "green"}
        sampleSize = 1000
        pts        = make([]client.Point, sampleSize)
    )

    p := fmt.Println

    rand.Seed(42)
    for i := 0; i < sampleSize; i++ {
        pts[i] = client.Point{
            Measurement: "shapes",
            Tags: map[string]string{
                "color": strconv.Itoa(rand.Intn(len(colors))),
                "shape": strconv.Itoa(rand.Intn(len(shapes))),
            },
            Fields: map[string]interface{}{
                "value": rand.Intn(sampleSize),
            },
            Time:      time.Now(),
            Precision: "s",
        }

        p("time.Now", time.Now)

        p("pts[i]", pts[i])
    }

    bps := client.BatchPoints{
        Points:          pts,
        Database:        MyDB,
        // RetentionPolicy: "default",
    }

    //p(bps)

    _, err := con.Write(bps)
    if err != nil {
        log.Fatal(err)
    }
}

func countRecords(con *client.Client) {

    q := fmt.Sprintf("select count(%s) from %s", "value", MyMeasurement)

    res, err := queryDB(con, q)
    if err != nil {
        log.Fatal(err)
    }

    count := res[0].Series[0].Values[0][1]
    log.Printf("Found a total of `%v records", count)
}

func last10Shapes(con *client.Client) {

    q := fmt.Sprintf("select * from %s limit %d", MyMeasurement, 20)

    res, err := queryDB(con, q)
    if err != nil {
        log.Fatal(err)
    }

    for i, row := range res[0].Series[0].Values {
        t, err := time.Parse(time.RFC3339, row[0].(string))
        if err != nil {
            log.Fatal(err)
        }
        //val, err := row[1].(json.Number).Int64()
        val := row[1].(string)
        //log.Printf("[%2d] %s: %03d\n", i, t.Format(time.Stamp), val)
        log.Printf("[%2d] %s: %s\n", i, t.Format(time.Stamp), val)
    }
}